package com.company.beauty.common.retry;

import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.company.beauty.common.config.properties.RetryProperties;
import com.company.nuwa.common.key.ApplicationNamedKeyGenerator;
import com.company.nuwa.redis.RedisExtTemplate;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Objects;

/**
 * <p>retry request redis handler</p >
 * bootstrap 提供 redis实现，若个别服务，需要支持其他持久化实现，可以新增类实现 {@link RetryRequestHandler}
 * 只需要确保 {@code weight} 权重大于当前redis实现即可
 *
 * @author youyoukele
 * @version 1.0
 * @date 2024/4/17 11:07
 */
@Slf4j
public class RetryRequestRedisHandler implements RetryRequestHandler {

    private static final RedisExtTemplate REDIS_EXT_TEMPLATE = SpringUtil.getBean(RedisExtTemplate.class);
    private static final RetryProperties RETRY_PROPERTIES = SpringUtil.getBean(RetryProperties.class);

    @Override
    public int weight() {
        return RetryRequestHandler.super.weight();
    }

    @Override
    public List<RetryRequest> getRetryList() {
        String queueKey = genRetryRequestQueueKey();
        List<RetryRequest> list = REDIS_EXT_TEMPLATE.opsForListWrapper().getAll(queueKey, RetryRequest.class);

        List<RetryRequest> result = Lists.newArrayList();
        for (RetryRequest retryRequest : list) {
            String statisticsKey = genRetryRequestStatisticsKey(retryRequest.getRequestId());
            Long increment = REDIS_EXT_TEMPLATE.opsForValueWrapper().increment(statisticsKey, 1, 3600);
            if (Objects.nonNull(increment) && increment <= RETRY_PROPERTIES.getMaximum()) {
                // 未超过最大重试次数
                result.add(retryRequest);
            } else {
                // 超过最大重试次数
                this.removeRetry(retryRequest);
            }
        }
        return result;
    }

    @Override
    public void addRetry(String requestId, String url, String requestBody) {
        RetryRequest retryRequest = new RetryRequest(requestId, url, requestBody, DateUtil.now());
        String key = genRetryRequestQueueKey();
        REDIS_EXT_TEMPLATE.opsForListWrapper().leftPush(key, retryRequest);
    }

    @Override
    public void removeRetry(RetryRequest retryRequest) {
        String queueKey = genRetryRequestQueueKey();
        REDIS_EXT_TEMPLATE.opsForListWrapper().remove(queueKey, 0, retryRequest);

        String statisticsKey = genRetryRequestStatisticsKey(retryRequest.getRequestId());
        REDIS_EXT_TEMPLATE.delete(statisticsKey);
    }

    /**
     * 注意，该队列为服务级别隔离
     * key的格式:  xxxx-service:RETRY_REQUEST_QUEUE
     *
     * @return
     */
    private String genRetryRequestQueueKey() {
        return ApplicationNamedKeyGenerator.genKey("RETRY_REQUEST_QUEUE");
    }

    /**
     * 注意，该key为服务级别隔离
     * key的格式:  xxxx-service:RETRY_REQUEST_STATISTICS:requestId
     *
     * @param requestId
     * @return
     */
    private String genRetryRequestStatisticsKey(String requestId) {
        return ApplicationNamedKeyGenerator.genKey("RETRY_REQUEST_STATISTICS", requestId);
    }

}
